//
// Created by benxb on 2021/10/2.
//
#pragma once

#ifndef BENXDB_PAGE_H
#define BENXDB_PAGE_H

#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <common/rwlatch.h>
#include <common/config.h>

namespace benxdb {

enum PageError {
    OK,
    NOT_ENOUGH_SPACE
};

class Page {
public:
    /** Constructor. Zeros out the block data_ */
    explicit Page() {
        ResetMemory();
    };

    /** Default destructor */
    ~Page() = default;

    /** @return the block id of this block */
    inline int GetPageId() { return page_id_; }

    /** @return true if the block in memory has been modified from the block on disk, false otherwise */
    inline bool IsDirty() { return is_dirty_; }

    /** Acquire the page write latch. */
    inline void WLatch() { rwlatch_.WLock(); }

    /** Release the page write latch. */
    inline void WUnlatch() { rwlatch_.WUnlock(); }

    /** Acquire the page read latch. */
    inline void RLatch() { rwlatch_.RLock(); }

    /** Release the page read latch. */
    inline void RUnlatch() { rwlatch_.RUnlock(); }

/** @return the actual data_ */
inline char* GetData() { return data_; }

protected:
    static_assert(sizeof(page_id_t) == 4, "");
    static constexpr size_t OFFSET_BLOCK_INIT = 0;

    inline void ResetMemory() {
        memset(data_, OFFSET_BLOCK_INIT, PAGE_SIZE);
    }

    /** The actual data_ array */
    char data_[PAGE_SIZE]{};
    /** Id of this block */
    page_id_t page_id_ = INVALID_PAGE_ID;
    /** The pin count of this block */
    int pin_count_ = 0;
    /** True if the block is dirty. For page swap */
    bool is_dirty_ = false;
    /** Page latch. */
    ReaderWriterLatch rwlatch_;
};

} // namespace benxdb

#endif //BENXDB_PAGE_H
